home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula 2
/
Nebula Two.iso
/
SourceCode
/
LispExample
/
Lisp.m
< prev
next >
Wrap
Text File
|
1995-06-12
|
4KB
|
194 lines
/*
** Lisp.m
** Lisp client object with message-based I/O.
** Lee Boynton, NeXT, Inc., 1989
*/
#import <mach.h>
#import <stdlib.h>
#import <string.h>
#import <fcntl.h>
#import <signal.h>
#import <sys/wait.h>
#import <dpsclient/dpsclient.h>
#import <defaults/defaults.h>
#import <appkit/Application.h>
#import <objc/List.h>
#import "Lisp.h"
@implementation Lisp
#define READ_BUF_SIZE (8191)
static char read_buf[READ_BUF_SIZE+1];
static void *read_lisp(int fd, Lisp *self)
{
extern int read();
NXEvent event;
int count = read(fd,read_buf,READ_BUF_SIZE);
id delegate = self->delegate;
BOOL tellDelegate = NO;
if (delegate && [delegate respondsTo:@selector(lispOutput:)])
tellDelegate = YES;
while (count > 0) {
read_buf[count] = '\0';
if (tellDelegate)
[delegate lispOutput:(const char *)read_buf];
if ([NXApp peekNextEvent:-1 into:&event waitFor:0.0 threshold:1])
break;
count = read(fd,read_buf,READ_BUF_SIZE);
}
}
static int launch(const char *name, const char **argv,
int *child_pid,
int *write_child_fd, int *read_child_fd)
{
extern int pipe();
extern int fork();
extern int dup2();
extern int close();
extern int execvp();
extern int fcntl();
extern int close();
int err, pid;
int p_to_child[2], p_from_child[2];
if ((err = pipe(p_to_child)) < 0)
return err;
if ((err = pipe(p_from_child)) < 0) {
close(p_to_child[0]);
close(p_to_child[1]);
return err;
}
if ((pid = fork()) == 0) {
dup2(p_to_child[0], 0);
dup2(p_from_child[1], 1);
dup2(p_from_child[1], 2);
close(p_to_child[1]);
close(p_from_child[0]);
execvp(name, argv);
exit(127);
}
if (pid == -1) {
close(p_to_child[0]);
close(p_to_child[1]);
close(p_from_child[0]);
close(p_from_child[1]);
return -1;
}
*child_pid = pid;
*write_child_fd = p_to_child[1];
close(p_to_child[0]);
*read_child_fd = p_from_child[0];
close(p_from_child[1]);
return fcntl(*read_child_fd,F_SETFL,FNDELAY);
}
static id lispList = nil;
static id findLispForPid(int pid) {
Lisp *self;
int i, max = [lispList count];
for (i=0; i<max; i++) {
self = (Lisp *)[lispList objectAt:i];
if (self->lisp_pid == pid)
return self;
}
return nil;
}
static void lispDied(int ignore) {
union wait epitaph;
int pid;
Lisp *self;
while (1) {
pid = wait3(&epitaph,WNOHANG,0);
if (pid > 0) {
if (self = findLispForPid(pid)) {
self->lisp_pid = 0;
break;
}
} else
break;
}
signal(SIGCHLD,&lispDied);
}
+ initialize
{
if (!lispList)
lispList = [List new];
signal(SIGCHLD,&lispDied);
return self;
}
+ new
{
int err;
const char *argv[2];
const char *imageName = NXGetDefaultValue([NXApp appName],"LispImage");
self = [super new];
argv[0] = imageName;
argv[1] = NULL;
[lispList addObject:self];
err = launch(imageName,argv,&lisp_pid, &lisp_in_fd,&lisp_out_fd);
if (err) {
[self free];
return nil;
}
DPSAddFD(lisp_out_fd,(DPSFDProc)read_lisp,(void *)self,1);
return self;
}
- free
{
extern int kill();
DPSRemoveFD(lisp_out_fd);
[lispList removeObject:self];
if (lisp_pid)
kill(lisp_pid,9);
return [super free];
}
- setDelegate:anObject
{
delegate = anObject;
return self;
}
- delegate
{
return delegate;
}
- inputLisp:(const char *)theString
{
extern int write();
int i, count = strlen(theString);
if (!lisp_pid || (count != write(lisp_in_fd,theString,count)))
return nil;
return self;
}
- interruptLisp
{
extern int kill();
if (lisp_pid && kill(lisp_pid,2))
return nil;
return self;
}
@end